/*--------------------------------------------------------------------

       +---------------------------------------------------+
       |                                                   |
       |     DETERMINISTIC  FINITE AUTOMATA  SIMULATOR     |
       |                                                   |
       +---------------------------------------------------+

          This  program  reads the DFA specifications form the
     file.
          The input string is accepted after the file has been
     read.
          Each  element of  the string is taken at a time. The
     new state is derived depending on current state  and  the
     input symbol.
          If at the end of the input string, the DFA is in one
     of  the  final states, the string is said to be accepted.
     Else, the string is said to be rejected.

--------------------------------------------------------------------*/

 # include <stdio.h>
 # include <conio.h>
 # include <string.h>
 # include <dir.h>

 struct delta {
                char pstate[5] ;
                char ipsym ;
                char nstate[5] ;
               } ;

 struct fini {
               char state[5] ;
              } ;

 struct file {
               char fname[15] ;
              } ;

 struct ipsym {
                char symbol ;
               } ;

 struct delta dfa[20] ;
 struct fini final[5] , states[5] ;
 struct file files[10] ;
 struct ipsym symbols[5] ;
 struct ffblk fil ;
 int lines , fstates , flines , qstates , no_sym ;

 # include <pop.c>

 int read_file (char fname[])
  {
    FILE *fp ;
    char string[80] , temp[5] ;
    int i , j ;

    if (( fp = fopen (fname,"r")) == NULL )
      return (-1) ;
    fgets (string,80,fp) ;
    while ( !feof(fp) )
     {
       for ( i = 0 ; string[i] == ' ' ; i++ ) ;
       switch ( string[i] )
        {
          case 'Q' : for ( ; string[i] != '{' ; i++ ) ;
                     i++ ;
                     for ( ; string[i] != '}' ; )
                      {
                        if ( string[i] == ',' )
                          i++ ;
                        for ( j = 0 ; (string[i] != '}') && (string[i] != ',') ; j++ , i++ )
                          states[qstates].state[j] = string[i] ;
                        states[qstates++].state[j] = '\0' ;
                       }
                     break ;
          case 'F' : for ( ; string[i] != '{' ; i++ ) ;
                     i++ ;
                     for ( ; string[i] != '}' ; )
                      {
                        if ( string[i] == ',' )
                          i++ ;
                        for ( j = 0 ; (string[i] != '}') && (string[i] != ',') ; j++ , i++ )
                          final[fstates].state[j] = string[i] ;
                        final[fstates++].state[j] = '\0' ;
                       }
                     break ;
          case '-' : for ( ; string[i] != '{' ; i++ ) ;
                     i++ ;
                     for ( ; string[i] != '}' ; )
                      {
                        if ( string[i] == ',' )
                          i++ ;
                        for ( ; (string[i] != '}') && (string[i] != ',') ; i++ )
                          symbols[no_sym++].symbol = string[i] ;
                       }
                     break ;
          case '#' : for ( ; string[i] != '(' ; i++ ) ;
                     i++ ;
                     for ( j = 0 ; string[i] != ',' ; j++ , i++ )
                       dfa[lines].pstate[j] = string[i] ;
                     dfa[lines].pstate[j] = '\0' ;
                     i++ ;
                     dfa[lines].ipsym = string[i] ;
                     for ( ; string[i] != '=' ; i++ ) ;
                     i++ ;
                     for ( ; string[i] == ' ' ; i++ ) ;
                     for ( j = 0 ; string[i] != '\n' ; j++ , i++ )
                       dfa[lines].nstate[j] = string[i] ;
                     dfa[lines++].nstate[j] = '\0' ;
                     break ;
          default  : break ;
         }
       fgets (string,80,fp) ;
      }
   }

 int find (char ip,char curr[])
  {
    int i ;

    for ( i = 0 ; i < lines ; i++ )
     {
       if ( ( strcmp (dfa[i].pstate,curr) == 0 ) && ( ip == dfa[i].ipsym ) )
         return (i) ;
      }
    return (-1) ;
   }

 int find_final (char state[])
  {
    int i ;

    for ( i = 0 ; i < fstates ; i++ )
     {
       if ( strcmp (final[i].state,state) == 0 )
         return (1) ;
      }
    return (-1) ;
   }

 main (int argc,char *argv[])
  {
    int index , i , col , BACK = 32 ;
    char str[40] , curr[5] , c ;

    if ( argc == 3 )
      if ( ( argv[2][1] == 'C' ) || ( argv[2][1] == 'c' ) )
        BACK = 23 ;

    if ( argc == 2 )
      if ( ( argv[1][1] == 'C' ) || ( argv[1][1] == 'c' ) )
        BACK = 23 ;

    EXECUTE_AGAIN : lines = 0 ;
    fstates = 0 ;
    flines = 0 ;
    qstates = 0 ;
    no_sym = 0 ;

    clear_rect_a (1,1,25,80,BACK) ;
    dbox (1,1,24,79) ;

    cattrib_rect (2,25,4,30,15) ;
    dbox (2,25,4,30) ;
    i_shadow2 (2,25,4,30,7) ;
    pstr_a (3,30," D F A    SIMULATOR",15) ;
    pcpy (5,31) ;

    if ( argc == 1 )
      i = findfirst ("*.DFA",&fil,32) ;
    if ( ( argc == 2 ) && ( strcmp (argv[1],"/C") ) == 0 )
      i = findfirst ("*.DFA",&fil,32) ;
    if ( ( argc == 2 ) && ( strcmp (argv[1],"/C") ) != 0 )
      i = findfirst (argv[1],&fil,32) ;
    if ( argc == 3 )
      i = findfirst (argv[1],&fil,32) ;
    while ( ( i == 0 ) && ( flines < 10 ) )
     {
       strcpy (files[flines++].fname,fil.ff_name) ;
       i = findnext (&fil) ;
      }

    if ( flines == 0 )
     {
       cattrib_rect (10,30,2,17,BACK) ;
       dbox (10,30,2,17) ;
       i_shadow2 (10,30,2,17,7) ;
       pstr_a (11,31,"No Entries Found",15) ;
       getch () ;
       clear_rect_a (1,1,25,80,15) ;
       return ;
      }

    cattrib_rect (10,30,flines+1,15,BACK) ;
    dbox (10,30,flines+1,15) ;
    i_shadow2 (10,30,flines+1,15,7) ;
    i = popup (11,31,flines,BACK) ;

    strcpy (str,files[i].fname) ;

    i = read_file (str) ;
    if ( i == -1 )
     {
       clear_rect_a (1,1,25,80,15) ;
       return ;
      }

    strcpy (curr,dfa[0].pstate) ;

    clear_rect_a (1,1,25,80,BACK) ;
    dbox (1,1,24,79) ;
    clear_rect_a (12,5,2,70,15) ;
    dbox (12,5,2,70) ;
    i_shadow2 (12,5,2,70,7) ;

    pstr_a (13,10,"Input String :",15) ;
    gotoxy (25,13) ;
    gets (str) ;

    clear_rect_a (1,1,25,80,15) ;
    dbox (1,1,24,79) ;

    pstr_a (3,5,"States : ",15) ;
    col = 15 ;
    for ( i = 0 ; i < qstates ; i++ ,col += 5 )
      pstr_a (3,col,states[i].state,15) ;

    pstr_a (5,5,"Input Symbol(s) : ",15) ;
    col = 25 ;
    for ( i = 0 ; i < no_sym ; i++ ,col += 3 )
      pchar_a (5,col,symbols[i].symbol,15) ;

    pstr_a (7,5,"Final State(s) : ",15) ;
    col = 22 ;
    for ( i = 0 ; i < fstates ; i++ ,col += 5 )
      pstr_a (7,col,final[i].state,15) ;

    pstr_a (9,5,"String : ",15) ;
    pstr_a (9,15,str,15) ;

    pstr_a (13,5,"Current State : ",15) ;
    col = 25 ;
    for ( i = 0 ; i < qstates ; i++ , col += 10 )
      pstr_a (13,col,states[i].state,15) ;
    col = 25 ;
    dbox (12,col-1,2,3) ;

    for ( i = 0 ; str[i] ; i++ )
     {
       pchar_a (10,i+15-1,' ',15) ;
       pchar_a (10,i+15,24,15) ;

       index = find (str[i],curr) ;

       if ( index >= 0 )
        {
          dbox (17,20,3,40) ;

          pstr_a (18,21,"Current State   Input Symbol  New State",15) ;
          gotoxy (26,19) ;
          printf ("%s",dfa[index].pstate) ;

          gotoxy (40,19) ;
          printf ("%c",dfa[index].ipsym) ;

          gotoxy (54,19) ;
          printf ("%s",dfa[index].nstate) ;

          getch () ;

          strcpy (curr,dfa[index].nstate) ;

          index = find (str[i],curr) ;

          ebox (12,col-1,2,3) ;
          col = ( ( index / no_sym ) * 10 ) + 25 ;
          dbox (12,col-1,2,3) ;
         }
       else
        {
          pstr_a (7,60,"Invalid Symbol",0x8F) ;
          goto INVALID_SYMBOL ;
         }
      }

    index = find_final (curr) ;

    if ( index == 1 )
     {
       pstr_a (22,23,"RESULT > String",23) ;
       pstr_a (22,39,"ACCEPTED",0x8F) ;
       pstr_a (22,48,"By The DFA",23) ;
      }
    else
     {
       INVALID_SYMBOL : pstr_a (22,21,"RESULT >  String",23) ;
       pstr_a (22,38,"NOT ACCEPTED",0x8F) ;
       pstr_a (22,51,"By The DFA",23) ;
      }

    pstr_a (24,25,"Do You Want To Continue ? (Y/N)  ",15) ;
    gotoxy (57,24) ;
    c = getche () ;
    if ( ( c == 'y' ) || ( c == 'Y' ) )
      goto EXECUTE_AGAIN ;
    gotoxy (1,25) ;
   }
